各種 Type 機制
- primitive type TS 中型別有兩種:
primitive type
、object type
其中 primitive type (原始型別) 有:boolean、number、string、null、undefined 和 ES6 的 Symbol宣告方式
let a: boolean = false;
let b: number = 98;
let c: string = "test";
let d: string = `${c}123`; // 嵌入變數
let e: undefined = undefined;
let f: null = null;
console.log(a);
console.log(b);
console.log(c);
console.log(d);
console.log(e);
console.log(f);不回傳用
void
function test(num: number): void {
console.log(num);
}
test(87);
- Union
宣告方式用
|
來分隔型別// 可以是 string or number 型別
let a: string | number
a = 'test'
console.log(a)
a = 87
console.log(a)用在 function,只能使用
共同的方法、屬性
toString()
是 number、string 共同的方法,所以可以使用;如果改成length
會報錯function getString(something: number | string): string {
return something.toString()
}
console.log(getString(98))
console.log(getString('test'))union type 的變數被 assign 時,會根據型別推論的規則推斷出當下型別
let something: string | number
// 目前是 string
something = 'test'
console.log(something.length)
// 目前是 number
something = 98
console.log(something.length) // 會報錯
- Pick (從一個型別中
取出子集
當成一個型別)可以增加閱讀性
type Info = {
name: string;
age: number;
account: string;
password: string;
phoneNumber: string;
};
// 從 Info 裡面取出 password,phoneNumber 成為一個新的 type
type Secret = Pick<Info, "password" | "phoneNumber">;
const secret: Secret = {
password: "password",
phoneNumber: "0987654321",
};
- Record
將兩個 type 組成一個分別是 key,value 的新 type
type CatName = 'A' | 'B' | 'C'
type CatInfo = {
age: number
breed: string
}
// Record<CatName, CatInfo> 是一個物件
// key 是 CatName,value 是 CatInfo
const cats: Record<CatName, CatInfo> = {
A: { age: 5, breed: 'AAA' },
B: { age: 10, breed: 'BBB' },
C: { age: 15, breed: 'CCC' }
}
- Partial / Required
Partial: 屬性都變成
option
Required: 屬性都變成
必須
type Student = {
name?: string
age: number
}
type PartialStudent = Partial<Student>
type RequiredStudent = Required<Student>
const student: Student = { age: 20 }
const partialStudent: PartialStudent = {}
const requiredStudent: RequiredStudent = { name: 'Sam', age: 27 }
- Intersection type
&
對 object type 會取
聯集
type Identity = {
id: string
name: string
}
type Contact = {
phone: string
email: string
}
type Employee = Identity & Contact
const employee: Employee = {
id: 'A001',
name: 'Tom',
phone: '0123456789',
email: 'abc@gmail.com'
}對 union type 會取
交集
type A = string | number
type B = string | boolean
// 會是交集
type C = A & B // string
- Any & Unknown 相同地方:
都可以接受任意型別
不同地方:
any 可以 assign 給任何型別
unknown 只能 assign 給 any or unknown
any 可以任意操作屬性 or 方法
unknown 要執行
型別斷言
或型別檢查
才能操作屬性 or 方法且通過編譯Any
any 可以被 assign 任意型別
// any 可以被 assign 任意型別
let a: any = "test";
console.log(a);
a = 87;
console.log(a);
a = true;
console.log(a);宣告時不指定型別,就會是 any
// 等同於 let something: any;
let something;
something = true;
console.log(something);
something = 98;
console.log(something);any 的問題
let a: any = 19;
let str: string = a;
// 編譯時期沒事,但執行時期會錯
console.log(str.toLowerCase());Unknown
只能 assign 給
unknown
orany
let a: unknown = 19;
// assign 給 unknown & any
let b: unknown = a;
let c: any = a;
// 會報錯!!
let str: string = a;沒有推斷是什麼型別之前,禁止操作屬性與方法
let a: unknown = "123";
if (typeof a === "string") {
console.log(a.toUpperCase()); // 推斷後可以用方法
}
- Never 用途:
無窮迴圈
function infiniteLoop(num: number): never {
while (true) {
console.log(num)
}
}throw exception
function generateError(message: string): never {
throw new Error(message)
}
- Omit (忽略特定屬性)
type Todo = {
title: string
description: string
completed: boolean
createdAt: number
}
type TodoPreview = Omit<Todo, 'description' | 'createdAt'>
const todo: TodoPreview = {
title: 'Finish recap 2021',
completed: false
}